﻿using System.Threading;
using System.Security.Permissions;
using System.Web.Hosting;
namespace System.Web
{
    public partial class NetHttpApplication
    {
        internal class CallHandlerExecutionStep : IExecutionStep
        {
            private NetHttpApplication _application;
            private AsyncCallback _completionCallback;
            private INetHttpAsyncHandler _handler;
            private bool _sync;

            internal CallHandlerExecutionStep(NetHttpApplication app)
            {
                _application = app;
                _completionCallback = new AsyncCallback(OnAsyncHandlerCompletion);
            }

            private void OnAsyncHandlerCompletion(IAsyncResult ar)
            {
                if (!ar.CompletedSynchronously)
                {
                    var context = _application.Context;
                    Exception error = null;
                    try
                    {
                        try { _handler.EndProcessRequest(ar); }
                        finally { ((NetHttpResponse)context.Response).GenerateResponseHeadersForHandler(); }
                    }
                    catch (Exception e2)
                    {
                        if ((e2 is ThreadAbortException) || ((e2.InnerException != null) && (e2.InnerException is ThreadAbortException)))
                            _application.CompleteRequest();
                        else
                            error = e2;
                    }
                    _handler = null;
                    context.WorkerRequest.SetStartTime();
                    ResumeSteps(error);
                }
            }

            private void ResumeSteps(Exception error)
            {
                _application.ResumeStepsFromThreadPoolThread(error);
            }

            void IExecutionStep.Execute()
            {
                var context = _application.Context;
                var handler = (context.Handler as INetHttpHandler);
                //if (handler != null)
                //{
                //    var workerRequest = (context.WorkerRequest as WebHostWorkerRequest);
                //    if ((workerRequest != null) && workerRequest.IsHandlerExecutionDenied())
                //    {
                //        _sync = true;
                //        var exception = new HttpException(0x193, "Handler_access_denied");
                //        exception.SetFormatter(new PageForbiddenErrorFormatter(context.Request.Path, "Handler_access_denied"));
                //        throw exception;
                //    }
                //}
                if (handler == null)
                    _sync = true;
                else if (handler is INetHttpAsyncHandler)
                {
                    var handler2 = (INetHttpAsyncHandler)handler;
                    _sync = false;
                    _handler = handler2;
                    var result = handler2.BeginProcessRequest(context, _completionCallback, null);
                    if (result.CompletedSynchronously)
                    {
                        _sync = true;
                        _handler = null;
                        try { handler2.EndProcessRequest(result); }
                        finally { ((NetHttpResponse)context.Response).GenerateResponseHeadersForHandler(); }
                    }
                }
                else
                {
                    _sync = true;
                    context.SyncContext.SetSyncCaller();
                    try { handler.ProcessRequest(context); }
                    finally
                    {
                        context.SyncContext.ResetSyncCaller();
                        ((NetHttpResponse)context.Response).GenerateResponseHeadersForHandler();
                    }
                }
            }

            bool IExecutionStep.CompletedSynchronously
            {
                get { return _sync; }
            }

            bool IExecutionStep.IsCancellable
            {
                get { return !(_application.Context.Handler is INetHttpAsyncHandler); }
            }
        }
    }
}
